﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using Forms=System.Windows.Forms;
using System.IO;
using System.Security.Cryptography;
using System.Text.RegularExpressions;
//using Crc32C;
using System.Timers;
using System.Collections.ObjectModel;
using Cursors = System.Windows.Input.Cursors;

namespace ZhwangTool
{
    /// <summary>
    /// PicSmallerUserControl.xaml 的交互逻辑
    /// </summary>
    public partial class PicSmallerUserControl : UserControl
    {
        public PicSmallerUserControl()
        {
            InitializeComponent();
        }

        List<string> fileSelects = new List<string>();

        private void AddFilesButton_Click(object sender, RoutedEventArgs e)
        {
            var fileDialog = new Forms.OpenFileDialog();

            listBox1.Items.Clear();

            fileDialog.Multiselect = true;


            fileSelects.Clear();

            if (fileDialog.ShowDialog() == System.Windows.Forms.DialogResult.OK)
            {
                foreach (var item in fileDialog.FileNames)
                {
                    fileSelects.Add(item);
                    listBox1.Items.Add(item);
                }

                //textBox1.Text = fileSelects[0];

                //textBox2.Text = textBox1.Text.Replace(".", "-ys.");

            }
        }

        private void Button9_Click(object sender, RoutedEventArgs e)
        {
            double kzxs = Convert.ToDouble(textBox18.Text);

            textBox20.Text = string.Empty;

            int n = fileSelects.Count;

            //progressBar2.Show();

            progressBar2.Maximum = n;

            int i = 1;

            var watch = new System.Diagnostics.Stopwatch();

            watch.Start();

            foreach (string item in fileSelects)
            {

                double giveScale = 1;

                double giveBuchang = 0.5;

                string originalFileFullName = item;

                string obFolderStr = "";

                if (rButtonA.IsChecked == true)
                {
                    obFolderStr = originalFileFullName.Replace(".", "-ys.");
                }
                else
                {
                    FileInfo f = new FileInfo(originalFileFullName);

                    if (Directory.Exists(System.IO.Path.Combine(f.DirectoryName, "ys")) == false)
                    {
                        f.Directory.CreateSubdirectory("ys");
                    }

                    obFolderStr = System.IO.Path.Combine(f.DirectoryName, "ys", f.Name);
                }



                int originSize = GetFileSize(originalFileFullName);

                int obSize = Convert.ToInt16(textBox10.Text);

                smallerPicByAuto(ref giveScale, ref giveBuchang, originalFileFullName, ref originSize, obFolderStr, obSize, kzxs);


                //textBox16.Text += originalFileFullName + "处理完毕";

                progressBar2.Value = i;

                i++;

                #region 暂时无用代码

                /*
                //
                //
                //
                //
                //通过缩小步长，逐渐接近目标值
                using (Image iSource = Image.FromFile(originalFileFullName))
                {
                    //tmpSize 指定为原始大小
                    int tmpSize = originSize;

                    //如果没有达到给定大小，就运行调整程序

                    while (tmpSize > obSize)
                    {
                        string tmpStr = "";

                        //记录压缩前的比例系数和压缩前的临时文件大小

                        double lastScale = giveScale;

                        int lastSize = tmpSize;

                        //改变压缩系数，通过调整giveBuchang值控制压缩系数的变化率

                        double blxs = giveScale * (1 - giveBuchang);

                        tmpStr = "当前步长为---" + giveBuchang.ToString("F4") + "当前比例为" + blxs.ToString("F4");

                        textBox16.Text += tmpStr + "\r\n";

                        //MessageBox.Show("当前步长为---" + giveBuchang.ToString("F4") + "当前比例为" + blxs.ToString("F4"));

                        //运行程序
                        bool run = scaleImg(iSource, blxs, obFolderStr);

                        //运行成功
                        if (run)
                        {
                            //运行后更新临时文件大小
                            tmpSize = GetFileSize(obFolderStr);

                            //MessageBox.Show("当前步文件大小为---" + tmpSize.ToString("F4"));

                            tmpStr = "当前步文件大小为---" + tmpSize.ToString("F4");

                            textBox16.Text += tmpStr + "\r\n";

                            //判断运行后临时文件与目标文件的大小，如果临时文件大小tmpSize仍然大于目标文件大小obSize，改变比例系数，不改变变化步长
                            if (tmpSize > obSize)
                            {
                                //MessageBox.Show("不需调整缩放步长，调整初始比例为" + blxs.ToString() + "继续运行递归函数");

                                giveScale = blxs;

                                originSize = tmpSize;

                            }
                            //如果临时文件大小tmpSize小于目标文件大小obSize，有可能是因为步长太大了，导致文件缩小的过快，
                            else
                            {
                                //若果这时候步长小于0.01说明变化率已经足够小了，那就结束运行了，不必做更多调整。
                                if (giveBuchang < 0.01)
                                {
                                    //originSize = tmpSize;

                                    //MessageBox.Show(" Program is over!");

                                    tmpStr =item+ "处理完毕!";

                                    textBox16.Text += tmpStr + "\r\n";

                                    break;

                                }
                                //若果这时候步长大于0.01说明还有更接近的可能，调整步长，减小比例系数变化率，以前一次运行前的比例系数、临时文件大小、步长的一半运行压缩程序。
                                else
                                {
                                    //MessageBox.Show("步长较大，缩小步长为原来的一半，按当前比例系数继续运行" + blxs.ToString() + "继续运行递归函数");

                                    tmpStr = "步长较大，缩小步长为原来的一半，按当前比例系数继续运行" + blxs.ToString() + "继续运行递归函数";

                                    textBox16.Text += tmpStr + "\r\n";


                                    giveBuchang = giveBuchang / 2;

                                    //将比例基数回复为前一次运行前的大小，此比例系数下，临时文件大小是大于目标文件大小的
                                    giveScale = lastScale;

                                    //通过跟小的步长计算下一次运行压缩程序时的比例系数

                                    blxs = giveScale * (1 - giveBuchang);

                                    //将临时文件大小调整为前一次运行前的大小，此时tmpSize大于目标文件大小originSize；

                                    tmpSize = lastSize;

                                }

                            }

                        }


                    }

                }

                */
                //
                //
                //
                //


                #endregion
            }

            watch.Stop();

            textBox20.Text = watch.Elapsed.TotalSeconds.ToString("F2") + "s";

            scrollViewer2.ScrollToEnd();

            System.Windows.MessageBox.Show("All files done!");



        }


        /// <summary>
        /// 获取文件的大小
        /// </summary>
        /// <param name="path"></param>
        /// <returns></returns>
        public int GetFileSize(string path)
        {
            System.IO.FileInfo fileInfo = null;
            try
            {
                fileInfo = new System.IO.FileInfo(path);

                fileInfo.Refresh();
            }
            catch
            {
                return 0;
            }
            if (fileInfo != null && fileInfo.Exists)
            {
                return (int)System.Math.Ceiling(fileInfo.Length / 1024.0);
            }
            else
            {
                return 0;
            }
        }


        private void smallerPicBySize(string originalFileFullName, string obFolderStr, string width, string height)
        {
            using (System.Drawing.Image iSource = System.Drawing.Image.FromFile(originalFileFullName))
            {
                int obWith = 0;

                bool b = int.TryParse(width, out obWith);

                int obHeight = 0;

                bool bb = int.TryParse(height, out obHeight);

                bool run = scaleImg(iSource, obWith, obHeight, obFolderStr);

            }


        }

        /// <summary>
        /// 缩放图片
        /// </summary>
        /// <param name="img">原图片</param>
        /// <param name="scaleValue">缩放宽比例,如果想缩小图片,小于100</param>
        /// <param name="yHeight">缩放高比例</param>
        /// <returns>返回处理后图片</returns>
        public bool scaleImg(System.Drawing.Image img, int xWith, int yHeight, string folderStr)
        {
            try
            {
                //计算处理后图片宽
                int i = 0;
                int j = 0;

                if (xWith > 0 && yHeight == 0)
                {
                    i = xWith;
                    j = Convert.ToInt32(img.Height * xWith / img.Width);

                }
                if (yHeight > 0 && xWith == 0)
                {
                    j = yHeight;

                    i = Convert.ToInt32(img.Width * yHeight / img.Height);

                }
                if (yHeight > 0 && xWith > 0)
                {
                    j = yHeight;

                    i = xWith;

                }


                using (System.Drawing.Image imgScale = new System.Drawing.Bitmap(i, j, System.Drawing.Imaging.PixelFormat.Format24bppRgb))
                {
                    //格式化图片
                    //System.Drawing.Image imgScale = new System.Drawing.Bitmap(i, j, System.Drawing.Imaging.PixelFormat.Format24bppRgb);
                    System.Drawing.Graphics g = System.Drawing.Graphics.FromImage(imgScale);
                    System.Drawing.Rectangle srcRect = new System.Drawing.Rectangle(0, 0, img.Width, img.Height);
                    System.Drawing.Rectangle desRect = new System.Drawing.Rectangle(0, 0, imgScale.Width, imgScale.Height);
                    g.Clear(System.Drawing.Color.White);
                    g.DrawImage(img, desRect, srcRect, System.Drawing.GraphicsUnit.Pixel);
                    //处理后的图片另存
                    imgScale.Save(folderStr, System.Drawing.Imaging.ImageFormat.Jpeg);
                    g.Dispose();
                    return true;
                }


            }
            catch (Exception)
            {

                return false;
            }


        }


        private void smallerPicByAuto(ref double giveScale, ref double giveBuchang, string originalFileFullName, ref int originSize, string obFolderStr, int obSize, double kzxs)
        {
            //通过缩小步长，逐渐接近目标值
            using (System.Drawing.Image iSource = System.Drawing.Image.FromFile(originalFileFullName))
            {
                //tmpSize 指定为原始大小
                int tmpSize = originSize;

                //如果没有达到给定大小，就运行调整程序

                while (tmpSize > obSize)
                {
                    string tmpStr = "";

                    //记录压缩前的比例系数和压缩前的临时文件大小

                    double lastScale = giveScale;

                    int lastSize = tmpSize;

                    //改变压缩系数，通过调整giveBuchang值控制压缩系数的变化率

                    double blxs = giveScale * (1 - giveBuchang);


                    tmpStr = "当前步长为---" + giveBuchang.ToString("F4") + "当前比例为" + blxs.ToString("F4");

                    textBox16.Text += tmpStr + "\r\n";


                    //MessageBox.Show("当前步长为---" + giveBuchang.ToString("F4") + "当前比例为" + blxs.ToString("F4"));

                    //运行程序
                    bool run = scaleImg(iSource, blxs, obFolderStr);

                    //运行成功
                    if (run)
                    {
                        //运行后更新临时文件大小
                        tmpSize = GetFileSize(obFolderStr);

                        tmpStr = "当前步文件大小为---" + tmpSize.ToString("F4");

                        Dispatcher.Invoke(new Action<string>(textBox16.AppendText), System.Windows.Threading.DispatcherPriority.Background, new object[] { tmpStr });

                        //textBox16.Text += tmpStr + "\r\n";

                        //判断运行后临时文件与目标文件的大小，如果临时文件大小tmpSize仍然大于目标文件大小obSize，改变比例系数，不改变变化步长
                        if (tmpSize > obSize)
                        {
                            //MessageBox.Show("不需调整缩放步长，调整初始比例为" + blxs.ToString() + "继续运行递归函数");

                            giveScale = blxs;

                            originSize = tmpSize;

                        }
                        //如果临时文件大小tmpSize小于目标文件大小obSize，有可能是因为步长太大了，导致文件缩小的过快，
                        else
                        {
                            //若果这时候步长小于 kzxs 说明变化率已经足够小了，那就结束运行了，不必做更多调整。
                            if (giveBuchang < kzxs)
                            {
                                //originSize = tmpSize;



                                break;

                            }
                            //若果这时候步长大于0.01说明还有更接近的可能，调整步长，减小比例系数变化率，以前一次运行前的比例系数、临时文件大小、步长的一半运行压缩程序。
                            else
                            {
                                //MessageBox.Show("步长较大，缩小步长为原来的一半，按当前比例系数继续运行" + blxs.ToString() + "继续运行递归函数");

                                tmpStr = "步长较大，缩小步长为原来的一半，按当前比例系数继续运行" + blxs.ToString() + "继续运行递归函数";

                                textBox16.Text += tmpStr + "\r\n";

                                giveBuchang = giveBuchang / 2;

                                //将比例基数回复为前一次运行前的大小，此比例系数下，临时文件大小是大于目标文件大小的
                                giveScale = lastScale;

                                //通过跟小的步长计算下一次运行压缩程序时的比例系数

                                blxs = giveScale * (1 - giveBuchang);

                                //将临时文件大小调整为前一次运行前的大小，此时tmpSize大于目标文件大小originSize；

                                tmpSize = lastSize;

                            }

                        }

                    }

                }

            }
        }

        private List<string> multiSmallerPicByAuto(ref double giveScale, ref double giveBuchang, string originalFileFullName, ref int originSize, string obFolderStr, int obSize, double kzxs)
        {
            List<string> runLogs = new List<string>();

            //通过缩小步长，逐渐接近目标值
            using (System.Drawing.Image iSource = System.Drawing.Image.FromFile(originalFileFullName))
            {
                //tmpSize 指定为原始大小
                int tmpSize = originSize;

                //如果没有达到给定大小，就运行调整程序

                while (tmpSize > obSize)
                {
                    string tmpStr = "";

                    //记录压缩前的比例系数和压缩前的临时文件大小

                    double lastScale = giveScale;

                    int lastSize = tmpSize;

                    //改变压缩系数，通过调整giveBuchang值控制压缩系数的变化率

                    double blxs = giveScale * (1 - giveBuchang);


                    tmpStr = "当前步长为---" + giveBuchang.ToString("F4") + "当前比例为" + blxs.ToString("F4");

                    runLogs.Add(tmpStr);

                    //textBox16.Text += tmpStr + "\r\n";


                    //MessageBox.Show("当前步长为---" + giveBuchang.ToString("F4") + "当前比例为" + blxs.ToString("F4"));

                    //运行程序
                    bool run = scaleImg(iSource, blxs, obFolderStr);

                    //运行成功
                    if (run)
                    {
                        //运行后更新临时文件大小
                        tmpSize = GetFileSize(obFolderStr);

                        //MessageBox.Show("当前步文件大小为---" + tmpSize.ToString("F4"));

                        tmpStr = "当前步文件大小为---" + tmpSize.ToString("F4");

                        //textBox16.Text += tmpStr + "\r\n";

                        runLogs.Add(tmpStr);

                        //判断运行后临时文件与目标文件的大小，如果临时文件大小tmpSize仍然大于目标文件大小obSize，改变比例系数，不改变变化步长
                        if (tmpSize > obSize)
                        {
                            //MessageBox.Show("不需调整缩放步长，调整初始比例为" + blxs.ToString() + "继续运行递归函数");

                            giveScale = blxs;

                            originSize = tmpSize;

                        }
                        //如果临时文件大小tmpSize小于目标文件大小obSize，有可能是因为步长太大了，导致文件缩小的过快，
                        else
                        {
                            //若果这时候步长小于 kzxs 说明变化率已经足够小了，那就结束运行了，不必做更多调整。
                            if (giveBuchang < kzxs)
                            {
                                //originSize = tmpSize;



                                break;

                            }
                            //若果这时候步长大于0.01说明还有更接近的可能，调整步长，减小比例系数变化率，以前一次运行前的比例系数、临时文件大小、步长的一半运行压缩程序。
                            else
                            {
                                //MessageBox.Show("步长较大，缩小步长为原来的一半，按当前比例系数继续运行" + blxs.ToString() + "继续运行递归函数");

                                tmpStr = "步长较大，缩小步长为原来的一半，按当前比例系数继续运行" + blxs.ToString() + "继续运行处理方法";

                                runLogs.Add(tmpStr);

                                //textBox16.Text += tmpStr + "\r\n";

                                giveBuchang = giveBuchang / 2;

                                //将比例基数回复为前一次运行前的大小，此比例系数下，临时文件大小是大于目标文件大小的
                                giveScale = lastScale;

                                //通过跟小的步长计算下一次运行压缩程序时的比例系数

                                blxs = giveScale * (1 - giveBuchang);

                                //将临时文件大小调整为前一次运行前的大小，此时tmpSize大于目标文件大小originSize；

                                tmpSize = lastSize;

                            }

                        }

                    }


                }

            }
            return runLogs;
        }

        /// <summary>
        /// 缩放图片
        /// </summary>
        /// <param name="img">原图片</param>
        /// <param name="scaleValue">缩放宽比例,如果想缩小图片,小于100</param>
        /// <param name="yHeight">缩放高比例</param>
        /// <returns>返回处理后图片</returns>
        public bool scaleImg(System.Drawing.Image img, double scaleValue, string folderStr)
        {
            //计算处理后图片宽
            int i = Convert.ToInt32(img.Width * scaleValue);
            //计算处理后图片高
            int j = Convert.ToInt32(img.Height * scaleValue);

            try
            {
                using (System.Drawing.Image imgScale = new System.Drawing.Bitmap(i, j, System.Drawing.Imaging.PixelFormat.Format24bppRgb))
                {

                    System.Drawing.Graphics g = System.Drawing.Graphics.FromImage(imgScale);
                    System.Drawing.Rectangle srcRect = new System.Drawing.Rectangle(0, 0, img.Width, img.Height);
                    System.Drawing.Rectangle desRect = new System.Drawing.Rectangle(0, 0, imgScale.Width, imgScale.Height);
                    g.Clear(System.Drawing.Color.White);
                    g.DrawImage(img, desRect, srcRect, System.Drawing.GraphicsUnit.Pixel);

                    //处理后的图片另存

                    imgScale.Save(folderStr, System.Drawing.Imaging.ImageFormat.Jpeg);

                    g.Dispose();


                }

                //格式化图片

                return true;

            }
            catch (Exception)
            {
                //throw;

                return false;
            }

        }

        private void Button10_Click(object sender, RoutedEventArgs e)
        {
            textBox20.Text = string.Empty;

            double kzxs = Convert.ToDouble(textBox18.Text);

            ParallelOptions options = new ParallelOptions();

            options.MaxDegreeOfParallelism = 4;

            List<string> strs = new List<string>();

            int obSize = Convert.ToInt16(textBox10.Text);

            var watch = new System.Diagnostics.Stopwatch();

            watch.Start();
            // rButtonA选中 表示直接在文件名后面加ys，没选中的话代表新建个袋ys的子目录
            if (rButtonA.IsChecked == true)
            {
                Parallel.ForEach(fileSelects, options, item =>
                {
                    double giveScale = 1;

                    double giveBuchang = 0.5;

                    string originalFileFullName = item;

                    string obFolderStr = originalFileFullName.Replace(".", "-ys.");

                    int originSize = GetFileSize(originalFileFullName);

                    List<string> tmpStrs = new List<string>();

                    tmpStrs = multiSmallerPicByAuto(ref giveScale, ref giveBuchang, originalFileFullName, ref originSize, obFolderStr, obSize, kzxs);

                    foreach (var str in tmpStrs)
                    {
                        strs.Add(str);

                    }

                });





            }
            else
            {

                Parallel.ForEach(fileSelects, options, item =>
                {
                    double giveScale = 1;

                    double giveBuchang = 0.5;

                    string originalFileFullName = item;

                    string obFolderStr = originalFileFullName.Replace(".", "-ys.");

                    FileInfo f = new FileInfo(originalFileFullName);

                    if (Directory.Exists(System.IO.Path.Combine(f.DirectoryName, "ys")) == false)
                    {
                        f.Directory.CreateSubdirectory("ys");
                    }

                    obFolderStr = System.IO.Path.Combine(f.DirectoryName, "ys", f.Name);

                    int originSize = GetFileSize(originalFileFullName);

                    List<string> tmpStrs = new List<string>();

                    tmpStrs = multiSmallerPicByAuto(ref giveScale, ref giveBuchang, originalFileFullName, ref originSize, obFolderStr, obSize, kzxs);

                    foreach (var str in tmpStrs)
                    {
                        strs.Add(str);

                    }

                });

            }

            watch.Stop();

            foreach (var item in strs)
            {
                textBox16.Text += item + "\r\n";

            }

            textBox20.Text = watch.Elapsed.TotalSeconds.ToString("F2") + "s";

            scrollViewer2.ScrollToEnd();

            System.Windows.MessageBox.Show("All files done!");
        }

        private void Button13_Click(object sender, RoutedEventArgs e)
        {

            int n = fileSelects.Count;

            //progressBar1.Show();

            progressBar2.Maximum = n;

            int i = 1;

            foreach (string item in fileSelects)
            {
                string originName = item;

                string objectName = originName.Replace(".", "-ys.");

                if (rButtonA.IsChecked == true)
                {
                    //objectName = originName.Replace(".", "-ys.");
                }
                else
                {
                    FileInfo f = new FileInfo(originName);

                    if (Directory.Exists(System.IO.Path.Combine(f.DirectoryName, "ys")) == false)
                    {
                        f.Directory.CreateSubdirectory("ys");
                    }

                    objectName = System.IO.Path.Combine(f.DirectoryName, "ys", f.Name);
                }

                smallerPicBySize(originName, objectName, textBox6.Text, textBox8.Text);

                textBox16.Text += originName + "处理完毕";

                progressBar2.Value = i;

                i++;

            }

            scrollViewer2.ScrollToEnd();

            System.Windows.MessageBox.Show("All work done");
        }

        private void Button14_Click(object sender, RoutedEventArgs e)
        {

            ParallelOptions options = new ParallelOptions();

            options.MaxDegreeOfParallelism = 3;

            string width = textBox6.Text;

            string height = textBox8.Text;

            if (rButtonA.IsChecked == true)
            {
                Parallel.ForEach(fileSelects, options, item =>
                {

                    string objectName = item.Replace(".", "-ys.");

                    smallerPicBySize(item, objectName, width, height);

                });
            }
            else
            {
                Parallel.ForEach(fileSelects, options, item =>
                {

                    string objectName = item.Replace(".", "-ys.");

                    FileInfo f = new FileInfo(item);

                    if (Directory.Exists(System.IO.Path.Combine(f.DirectoryName, "ys")) == false)
                    {
                        f.Directory.CreateSubdirectory("ys");
                    }

                    objectName = System.IO.Path.Combine(f.DirectoryName, "ys", f.Name);

                    smallerPicBySize(item, objectName, width, height);

                });

            }

            scrollViewer2.ScrollToEnd();

            System.Windows.MessageBox.Show("All work done");
        }

        private void ListBox1_DragEnter(object sender, DragEventArgs e)
        {
            if (e.Data.GetDataPresent(DataFormats.FileDrop))
                //e.Effect = DragDropEffects.All;    //重要代码：表明是所有类型的数据，比如文件路径

                e.Effects = DragDropEffects.Link;

            else
                e.Effects = DragDropEffects.None;
        }

        private void ListBox1_Drop(object sender, DragEventArgs e)
        {
            string[] filePaths = (string[])e.Data.GetData(DataFormats.FileDrop);

            if (filePaths != null && filePaths.Length > 0)
            {
                foreach (string item in filePaths)
                {

                    string fileExtension = System.IO.Path.GetExtension(item).ToLower();

                    string[] imageExtensions = { ".jpg", ".jpeg", ".png", ".bmp" };

                    if (imageExtensions.Contains(fileExtension)&&listBox1.Items.Contains(item) ==false)
                    {

                        listBox1.Items.Add(item);
                        
                    }

                }
                
            }
        }
    }
}
